﻿using System;
using System.Collections.Generic;
using System.Configuration;
using System.Globalization;
using System.IO;
using System.Linq;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Net.Http.Formatting;

using Sustainalytics.ClientDW.Entities;
using Sustainalytics.DataLayer.ConnectionStrings;
using Sustainalytics.DataLayer.Shared;
using Sustainalytics.Entities.ConnectionStrings;
using Sustainalytics.LongRunningTaskManager;
using Sustainalytics.LongRunningTaskManager.Interface;
using Sustainalytics.Utils.Enumerable;
using Sustainalytics.ReportGenerator.BL;
using Sustainalytics.Auth.Common;
using Sustainalytics.Entities;

namespace Sustainalytics.ESGRatings.Tasks
{
    public class ControversyReportDownloadTask : ILongRunningTask
    {
        private Guid _companyId;

        private readonly IRepositoryCollection<RenderResult> _repository;
        private readonly IRepositoryCollection<CorporateData> _repositoryCorporateData;
        private string _mongoUrl;
        private readonly string _clientDWConnectionString;

        public ControversyReportDownloadTask(IRepositoryCollection<RenderResult> repository)
        {
            _repository = repository;
        }

        public ControversyReportDownloadTask(string MongoUrl)
        {
            _mongoUrl = MongoUrl;
            _repository = new RepositoryCollectionWithFile<RenderResult>(_mongoUrl, "ControversyReportPDF"); 
        }

        public ControversyReportDownloadTask()
            : this(ConnectionStringsManager.GetInstance(ConnectionStringsRepository.GetInstance(ConfigurationManager.ConnectionStrings["ClientPlatform"].ConnectionString))
                                            .GetConnectionString(ConnectionStringType.ControversyReportPDF))
        {
            var connectionStringsManager = ConnectionStringsManager.GetInstance(ConnectionStringsRepository.GetInstance(ConfigurationManager.ConnectionStrings["ClientPlatform"].ConnectionString));

            _clientDWConnectionString = connectionStringsManager.GetConnectionString(ConnectionStringType.ClientDW);

            _repositoryCorporateData = new RepositoryCollection<CorporateData>(_clientDWConnectionString);


        }


        public LongRunningTaskTypeEnum Type
        {
            get { return LongRunningTaskTypeEnum.ControversyReportPDF;}
        }


        public object Start(LongRunningTaskContext context)
        {
            _companyId = JsonConvert.DeserializeObject<Guid>(context.ParamJson);

            var url = ConfigurationManager.AppSettings["ControversiesServiceUrl"];
            var uri = new Uri(string.Format("{0}/api/v1", url));

            return TryGetReport(context, uri, _companyId);
        }

        private LongRunningTaskS3FileResult TryGetReport(LongRunningTaskContext context, Uri uri, Guid companyId)
        {
            if (uri == null)
                throw new ArgumentNullException("uri");

            if (companyId == null)
                throw new ArgumentNullException("companyId");

            try
            {
                var requestUri = string.Format("{0}/company/{1}/controversyReport", uri, companyId);

                var jsonMediaTypeFormatter = new JsonMediaTypeFormatter
                {
                    SerializerSettings =
                    {
                        ContractResolver = new CamelCasePropertyNamesContractResolver()
                    }
                };

                var ticketDataFormat = new CustomAccessTokenFormat();
                var accessToken = ticketDataFormat.Protect(context.Ticket);

                using (var client = new HttpClient())
                {
                    client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
                    client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);

                    var executionResult = client.GetAsync(requestUri).Result;

                    if (executionResult.IsSuccessStatusCode)
                    {
                        var result = executionResult.Content.ReadAsAsync<PdfReportExecutionResult>(jsonMediaTypeFormatter.Yield()).Result;

                        if (result != null)
                        {
                            return new LongRunningTaskS3FileResult
                            {
                                MimeType = "application/pdf",
                                Bucket = result.S3Bucket,
                                FileName = result.FileName,
                                Key = result.S3Key
                            };
                        }                            
                    }

                    SetErrorToContext(context);

                    LongRunningTaskManagerEventSource.Log.TaskFailed(LongRunningTaskTypeEnum.ControversyReportPDF, "", "",
                        string.Format("Failed to get the Controversy Report for company ID={0}", companyId));

                    return null;
                }
            }
            catch (HttpRequestException httpRequestException)
            {
                LongRunningTaskManagerEventSource.Log.TaskFailed(LongRunningTaskTypeEnum.ControversyReportPDF, "", "", string.Format("Controversy.Error {0}", httpRequestException));
                context.TaskStatus.AddError(new LongRunningTaskError
                {
                    ErrorCode = 7003,
                    Arguments = new List<string> { httpRequestException.Message }
                });
            }

            return null;
        }


        private void SetErrorToContext(LongRunningTaskContext context)
        {
            context.Title = "Failed to get the Controversy Report for specified company";
            context.TaskStatus.AddError(new LongRunningTaskError
            {
                ErrorCode = 7001,
                Arguments = new List<string> { "Failed to get the Controversy Report for specified company" }
            });
        }
    }
}
